package com.angel.resourceBundle.contexts;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.angel.resourceBundle.exceptions.CurrentInternationalizerException;
import com.angel.resourceBundle.internationalizer.Internationalizer;



/**
 * {@link ComplexResourceBundleContext} was created because of you can extends from him to implements a specific resource bundle application.
 * Here you must decide how is going to create the application labels, and default texts for you application.
 * A default implementation can be the follow:
 * If you have two idioms for you application, for example english and spanish.
 * In the abstract method {@code initializeContext()} you must initialize all the idioms in you application, and your key application can be
 * generated by the follow string: [APPLICATIONNAME]_[IDIOM]_[SPECIFIC_STRINGKEY], being:
 * [APPLICATIONNAME]: Your application name.
 * [IDIOM] : Current selected idiom.
 * [SPECIFIC_STRINGKEY] A specific string key, for example a label or a text.
 *
 * @author William
 *
 */
public abstract class ComplexResourceBundleContext extends ResourceBundleContext{

	private static final String RESOURCE_BUNDLE_MANAGER_TYPE = "COMPLEX";

	private List<Internationalizer> internationalizersAvailables;

	public ComplexResourceBundleContext(){
		super();
		this.internationalizersAvailables = new ArrayList<Internationalizer>();
	}

	public ComplexResourceBundleContext(Internationalizer ...internationalizers){
		super();
		this.internationalizersAvailables = new ArrayList<Internationalizer>();
		this.addAllByArray(internationalizers);
	}

	public ComplexResourceBundleContext(Collection<Internationalizer> internationalizer){
		super();
		this.internationalizersAvailables = new ArrayList<Internationalizer>(internationalizer);
	}

	/**
	 * Default application constructor.
	 */
	public ComplexResourceBundleContext(String keySeparator){
		super(keySeparator);
		this.internationalizersAvailables = new ArrayList<Internationalizer>();
	}

	@Override
	public String getCurrentLanguageName() {
		Internationalizer current = this.findCurrentInternationalizer();
		return current != null ? current.getName() : null;
	}

	@Override
	public String getResourceBundleManagerType() {
		return RESOURCE_BUNDLE_MANAGER_TYPE;
	}

	/**
	 * @return the currentInternationalizer
	 */
	public Internationalizer findCurrentInternationalizer() {
		Internationalizer current = null;
		for(Internationalizer i : this.internationalizersAvailables){
			if(i.getCurrent()){
				current = i;
				break;
			}
		}
		if(current == null){
			throw new CurrentInternationalizerException("Not current internationalizer [" + this.internationalizersAvailables.size() + " internationalizers] found at complex context.");
		}
		return current;
	}

	public void addInternationalizer(Internationalizer internationalizer, Boolean asCurrent) {
		if(asCurrent){
			Internationalizer current = this.findCurrentInternationalizer();
			current.setCurrent(Boolean.FALSE);
			this.addInternationalizer(internationalizer);
		} else {
			this.addInternationalizer(internationalizer);
		}
	}

	public void addInternationalizer(Internationalizer internationalizer) {
		if((!this.containsInternationalizer(internationalizer.getName()) &&
				(this.hasCurrentInternationalizer() && !internationalizer.getCurrent()))
				|| (!this.hasCurrentInternationalizer() && internationalizer.getCurrent())){
			this.internationalizersAvailables.add(internationalizer);
		} else {
			throw new CurrentInternationalizerException("Internationalizer [" + internationalizer.getName() + "] not added because it was setted as current. Current internationalizer already was defined. ");
		}
	}

	private boolean hasCurrentInternationalizer() {
		boolean hasCurrent = false;
		for(Internationalizer i : this.internationalizersAvailables){
			if(i.getCurrent()){
				hasCurrent = true;
				break;
			}
		}
		return hasCurrent;
	}

	public boolean containsInternationalizer(String name) {
		boolean contains = false;
		for(Internationalizer i: this.internationalizersAvailables){
			if(i.getName().equalsIgnoreCase(name)){
				contains = true;
				break;
			}
		}
		return contains;
	}

	public <T extends Internationalizer> void addAllByColletion(Collection<T> internationalizers) {
		if(internationalizers != null && internationalizers.size() > 0){
			for(Internationalizer i: internationalizers){
				this.addInternationalizer(i);
			}
		}
	}

	public void addAllByArray(Internationalizer ...internationalizers) {
		if(internationalizers != null && internationalizers.length > 0){
			for(Internationalizer i: internationalizers){
				this.addInternationalizer(i);
			}
		}
	}
}
